package com.szty.mod_jyzs.ui.questionExplain

import android.content.Context
import android.content.Intent
import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
import android.media.MediaRecorder
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
import android.os.*
import androidx.annotation.IntDef
import com.blankj.utilcode.util.ScreenUtils
import com.blankj.utilcode.util.TimeUtils

/**
 *@author : created by SunJH
 *时间：2021/7/26 002615
 *作用： 屏幕录制服务
 */
class ScreenRecordUtils(val context: Context) {
    private val TAG = this::class.java.simpleName
    private var isVideoSd = false
    private var mScreenDensity = 0f
    private var mScreenHeight: Int = 0
    private var mScreenWidth: Int = 0

    private var mResultCode = 0
    private var mresultData: Intent? = null
    private var mMediaProjection: MediaProjection? = null
    private var mMediaRecorder: MediaRecorder? = null
    private var mVirtualDisplay: VirtualDisplay? = null
    var callTime: ((String) -> Unit)? = null
    var callMaxTime:(()->Unit)? = null
    var callRecordStatus:((Int)->Unit)? = null
    var filePath:String = ""
    private var time: Int = 0
    private val maxTime = 60*60*3
    private val mHandler = Handler(Looper.myLooper()!!) {
        when (it.what) {
            1 -> {
                if(screenRecordStatus == STOP) return@Handler true
                time ++
                if(time<maxTime){
                    callTime?.invoke(getGapTime(time))
                }else{
                    stopScreenRecord()
                    callMaxTime?.invoke()
                }
            }
        }
        return@Handler true
    }

    @Retention(AnnotationRetention.SOURCE)
    @IntDef(STOP, PAUSE, RUNNING)
    annotation class ScreenRecordStatus

    @ScreenRecordStatus
    var screenRecordStatus = STOP

    companion object{
        const val STOP = 0x1
        const val PAUSE = 0x2
        const val RUNNING = 0x3
    }

    /**
     * 将秒转换成时分秒
     * @param time 秒
     * 1*60*60
     */
    private fun getGapTime(time: Int): String {
        val hours  = time / (60 * 60)
        val minutes = (time -(hours*60*60))/60
        val second =time -((hours*60*60))-(minutes*60)
        return "${addZero(hours)}:${addZero(minutes)}:${addZero(second)}"
    }

   private fun addZero(params: Int):String {
        return if(params<10) "0${params}" else params.toString()
    }

    fun pauseScreenRecord() {
        if(screenRecordStatus == STOP)return
        screenRecordStatus = PAUSE
        mMediaRecorder?.pause()
        callRecordStatus?.invoke(screenRecordStatus)
    }
    fun resumeScreenRecord(){
        if(screenRecordStatus == STOP)return
        startCountTime()
        mMediaRecorder?.resume()
    }
    fun stopScreenRecord() {
        if(screenRecordStatus == STOP)return
        screenRecordStatus = STOP
        callRecordStatus?.invoke(screenRecordStatus)
        time = 0
        if (mVirtualDisplay != null) {
            mVirtualDisplay?.release()
            mVirtualDisplay = null
        }
        if (mMediaRecorder != null) {
            mMediaRecorder?.setOnErrorListener(null)
            mMediaRecorder?.stop()
            mMediaRecorder?.reset()
        }
        if (mMediaProjection != null) {
            mMediaProjection?.stop()
            mMediaProjection = null
        }
    }

    fun startScreenRecord(intent: Intent) {
        startCountTime()
        mResultCode = intent.getIntExtra("resultCode", 1)
        mresultData = intent
        initScreenbaseInfo()
        mMediaProjection = createMediaProjection()
        mMediaRecorder = createMediaRecorder()
        mVirtualDisplay = createVirtualDisplay()
        mMediaRecorder?.start()
    }

    private fun createVirtualDisplay(): VirtualDisplay {
        return mMediaProjection!!.createVirtualDisplay(
            TAG,
            mScreenWidth,
            mScreenHeight,
            mScreenDensity.toInt(),
            DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mMediaRecorder!!.surface,
            null,
            null
        )
    }

    private fun startCountTime() {
        if(screenRecordStatus == RUNNING) return
        screenRecordStatus = RUNNING
        callRecordStatus?.invoke(screenRecordStatus)

        Thread {
            while (screenRecordStatus == RUNNING) {
                val obtain = Message.obtain()
                obtain.what = 1
                mHandler.sendMessage(obtain)
                Thread.sleep(1000)
            }
        }.start()
    }

    private fun createMediaRecorder(): MediaRecorder {
        val curTime = TimeUtils.millis2String(System.currentTimeMillis(), "yyyy-MM-dd-HH-mm-ss")
            .replace(" ", "")
        var videoQuality = "HD"
        if (isVideoSd) videoQuality = "SD"
        return MediaRecorder().apply {
            setVideoSource(MediaRecorder.VideoSource.SURFACE)
            setAudioSource(MediaRecorder.AudioSource.MIC)
            setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
             filePath =
                "${context.getExternalFilesDir(Environment.DIRECTORY_MOVIES)?.absolutePath}/${videoQuality}${curTime}.mp4"
            setOutputFile(filePath)
            setVideoSize(mScreenWidth, mScreenHeight)
            setVideoFrameRate(30)
            setVideoEncodingBitRate(5 * mScreenWidth * mScreenHeight)
            setVideoEncoder(MediaRecorder.VideoEncoder.H264)
            setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
            try {
                prepare()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    private fun createMediaProjection(): MediaProjection {
        val mediaProjectionManager =
            context.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
        return mediaProjectionManager.getMediaProjection(mResultCode, mresultData!!)
    }

    private fun initScreenbaseInfo() {
        mScreenHeight = ScreenUtils.getScreenHeight()
        mScreenWidth = ScreenUtils.getScreenWidth()
        mScreenDensity = ScreenUtils.getScreenDensity()
    }
}